from typing import Generator, TypeVar
from sqlalchemy import create_engine
from sqlalchemy.engine import Engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import Session, sessionmaker
from config.settings import settings

# 类型变量，用于增强类型提示
T = TypeVar('T')

# 创建数据库引擎
# 引擎是SQLAlchemy与数据库交互的核心，负责管理连接池
engine: Engine = create_engine(
    url=settings.database_url,  # 数据库连接字符串（从环境变量加载）
    echo=settings.environment == "development",  # 开发环境打印SQL日志，生产环境关闭
    pool_size=settings.db_pool_size,  # 连接池常驻连接数（建议根据并发量设置）
    max_overflow=settings.db_max_overflow,  # 连接池满时允许临时创建的连接数
    pool_recycle=3600,  # 连接存活时间（秒），避免数据库超时断开（如MySQL wait_timeout默认8小时）
    pool_pre_ping=True,  # 执行操作前检查连接有效性，自动重连失效连接
    pool_use_lifo=True,  # 连接池使用LIFO策略（最后创建的连接优先复用），提升性能
    # 生产环境建议添加连接超时设置（根据数据库类型调整参数）
    connect_args={
        # PostgreSQL示例：连接超时5秒
        # "connect_timeout": 5,
        # MySQL示例：读取超时10秒
        # "read_timeout": 10,
        # "write_timeout": 10,
    }
)

# 创建会话工厂
# 会话工厂用于生成数据库会话（类似数据库连接），所有数据库操作通过会话进行
SessionLocal: sessionmaker[Session] = sessionmaker(
    bind=engine,
    autocommit=False,  # 关闭自动提交，需手动调用session.commit()提交事务
    autoflush=False,  # 关闭自动刷新，避免未提交的修改被自动同步到数据库
    expire_on_commit=False  # 提交后不失效对象，可继续访问已提交数据
)

# 声明式基础类
# 所有数据模型类需继承此类，实现ORM映射
Base = declarative_base()


def get_db() -> Generator[Session, None, None]:
    """
    数据库会话依赖项生成器

    功能：
    1. 从会话工厂创建新会话
    2. 通过yield将会话提供给调用方（如接口函数）
    3. 无论是否发生异常，最终都会关闭会话释放资源

    适用场景：
    - FastAPI接口中通过Depends(get_db)注入数据库会话
    - 其他需要临时使用数据库连接的场景
    """
    db: Session = SessionLocal()
    try:
        yield db  # 提供会话给调用方
    except Exception as e:
        # 发生异常时回滚事务（可选，根据业务需求调整）
        db.rollback()
        raise  # 重新抛出异常，让上层处理
    finally:
        db.close()  # 确保会话最终关闭，释放连接回连接池
